package xyz.thetbw.autocode.utils

import org.apache.velocity.app.Velocity
import org.apache.velocity.context.Context
import xyz.thetbw.autocode.Config
import java.io.*
import java.util.*

/**
 * Velocity 工具集
 */
object VelocityUtils{

    init {
        //这些指令暂时不可用
        Velocity.addProperty("userdirective",StringJoiner(",").apply {
            add("xyz.thetbw.autocode.velocity.LineToHump")
            add("xyz.thetbw.autocode.velocity.Uppercase")
            add("xyz.thetbw.autocode.velocity.UppercaseFirst")
            add("xyz.thetbw.autocode.velocity.LowercaseFirst")
        }.toString())

        if (Config.instance.renderStrictMode){
            Velocity.setProperty(Velocity.RUNTIME_REFERENCES_STRICT,true)
        }
        Velocity.setProperty(Velocity.INPUT_ENCODING,Config.instance.inputCharset)
        Velocity.setProperty(Velocity.OUTPUT_ENCODING,Config.instance.outputCharset)
    }

    private fun prepareReader(file: File): Reader{
        if (!file.exists()){
            throw FileNotFoundException(file.canonicalPath + " not found")
        }
        return InputStreamReader(FileInputStream(file),Config.instance.inputCharset)
    }

    private fun prepareWriter(file: File): Writer{
        return OutputStreamWriter(FileOutputStream(file),Config.instance.outputCharset)
    }

    fun render(text: String,context: Context): String{
        val write = CharArrayWriter()
        write.use {
            Velocity.evaluate(context,write,"evaluate",text)
            val charArray = write.toCharArray()
            return String(charArray)
        }
    }

    /**
     * @param reader 流不会关闭
     */
    fun render(reader: Reader,context: Context): String{
        val write = CharArrayWriter()
        write.use {
            Velocity.evaluate(context,write,"evaluate",reader)
            val charArray = write.toCharArray()
            return String(charArray)
        }
    }

    fun render(inFile: File,context: Context): String{
        val write = CharArrayWriter()
        val reader = prepareReader(inFile)
        write.use {
            Velocity.evaluate(context,write,inFile.canonicalPath,reader)
            val charArray = write.toCharArray()
            return String(charArray)
        }
    }

    fun renderToFile(text: String,context: Context,outFile:File){
        val write = prepareWriter(outFile)
        write.use {
            Velocity.evaluate(context,write,outFile.canonicalPath,text)
        }
    }

    fun renderToFile(inFile: File,context: Context,outFile: File){
        val write = prepareWriter(outFile)
        val input = prepareReader(inFile)
        write.use {
            Velocity.evaluate(context,write,outFile.canonicalPath,input)
        }
    }

}